package com.example.redisson.redisson;

import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

@Service
public class ExclusiveLockService {

    @Resource
    private RedissonClient redissonClient;

    /**
     * Redisson 独占锁示例
     */
    public void exclusiveLock() {

        // 获取一个分布式锁对象，如果不存在则创建一个
        RLock lock = redissonClient.getLock("myLock");
        try {
            // 尝试获取锁，如果无法立即获取，则等待。获取的是一个独占锁，也称为写锁或互斥锁。
            // 使用 lock() 方法获取锁。如果锁已经被其他线程持有，调用线程将等待直到获得锁。
            // 推荐使用 tryLock() 方法，无参数的这个方法尝试立即获取锁。如果锁可用，则获取锁并返回 true；如果锁不可用，则不等待立即返回 false。因此，这个方法没有超时/等待时间、不会阻塞。
            lock.lock();
            // 执行需要同步的操作
            System.out.println("已获取锁，下面执行同步操作...");
            // 执行临界区内的代码
            // 在计算机科学中，“临界区”是指一段代码，这段代码只能由一个进程或线程在任意时刻执行。
            // 临界区的概念主要用于多线程或多进程环境中的同步控制，以避免并发访问共享资源时可能出现的竞争条件。
            System.out.println("正在对共享数据执行个人操作...");

            // 模拟一些耗时操作
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // 中断异常，获取锁失败，执行其他操作
            System.out.println("无法获取锁，正在执行替代操作...");
            // 中断当前线程
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
            // 使用 unlock() 方法释放锁。通常最好将释放锁的操作放在 finally 块中，以确保即使发生异常也能释放锁。
        } finally {
            // 完成所有操作后，如果锁还被当前线程持有，则释放锁
            if (lock.isHeldByCurrentThread()) {
                // 释放锁
                lock.unlock();
            }
        }

        // 尝试获取锁，如果获取失败，则执行其他操作。获取的是一个独占锁，也称为写锁或互斥锁。
        // tryLock() 这个方法尝试立即获取锁。如果锁可用，则获取锁并返回 true；如果锁不可用，则不等待立即返回 false。因此，这个方法没有超时/等待时间、不会阻塞。
        // 如果你想要设置锁的超时时间，可以使用 tryLock(long time, TimeUnit unit) 方法，其中 leaseTime 是锁的有效时间，unit 是时间单位。
        // 也就是说，每个线程最长持有锁的时间为 time 时间单位。如果线程在持有时间内任务还没有完成，没有主动释放锁，则锁会被自动释放，避免死锁。超长时间占有锁，导致其他线程无法获取锁。
        if (lock.tryLock()) {
            try {
                // 执行需要同步的操作
                System.out.println("已获取锁，执行同步操作...");
            } finally {
                // 释放锁
                lock.unlock();
            }
        } else {
            // 获取锁失败，执行其他操作
            System.out.println("无法获取锁，正在执行替代操作...");
        }


        redissonClient.getSpinLock("mySpinLock"); // 获取一个自旋锁对象，如果不存在则创建一个
        redissonClient.getSemaphore("mySemaphore"); // 获取一个信号量对象，如果不存在则创建一个
        redissonClient.getAtomicLong("myAtomicLong"); // 获取一个原子计数器对象，如果不存在则创建一个

    }

}
